package com.aiitec.camera;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.ImageFormat;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.SurfaceTexture;
import android.graphics.YuvImage;
import android.hardware.Camera;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.KeyEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.TextureView;
import android.view.Window;
import android.view.WindowManager;
import android.widget.LinearLayout;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.SoftReference;
import java.util.List;

/**
 * @author Anthony
 * @version 1.0
 *          createTime 2017/9/25.
 */

public class LiveCameraActivity extends Activity implements TextureView.SurfaceTextureListener {
    private static final String TAG = "TAG_CAMERA";
    private static int WIDTH = 0;
    private static int HEIGHT = 0;
    private Camera mCamera;
    private TextureView mTextureView;

    private SurfaceView surfaceView;
    private boolean isRun;
    private Paint paint = new Paint();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        this.requestWindowFeature(Window.FEATURE_NO_TITLE);//去掉标题栏
        this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);//去掉信息栏
//        getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION|View.SYSTEM_UI_FLAG_IMMERSIVE);
//        getWindow().addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);

        mTextureView = new TextureView(this);
        mTextureView.setSurfaceTextureListener(this);
        surfaceView = new SurfaceView(this);
        surfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {
            @Override
            public void surfaceCreated(SurfaceHolder holder) {

            }

            @Override
            public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

            }

            @Override
            public void surfaceDestroyed(SurfaceHolder holder) {

            }
        });
        DisplayMetrics metrics = getResources().getDisplayMetrics();
        WIDTH = metrics.widthPixels;
        HEIGHT = metrics.heightPixels;
        LinearLayout layout = new LinearLayout(this);
        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(WIDTH / 2, HEIGHT);
        mTextureView.setLayoutParams(params);
        surfaceView.setLayoutParams(params);
        layout.addView(mTextureView);
        layout.addView(surfaceView);
        setContentView(layout);


    }

    @Override
    protected void onStop() {
        super.onStop();

    }
    private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {
        final double ASPECT_TOLERANCE = 0.1;
        double targetRatio = (double) w / h;
        if (sizes == null) {
            return null;
        }

        Camera.Size optimalSize = null;
        double minDiff = Double.MAX_VALUE;

        int targetHeight = h;

        // Try to find an size match aspect ratio and size
        for (Camera.Size size : sizes) {
            double ratio = (double) size.width / size.height;
            if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) {
                continue;
            }
            if (Math.abs(size.height - targetHeight) < minDiff) {
                optimalSize = size;
                minDiff = Math.abs(size.height - targetHeight);
            }
        }

        // Cannot find the one match the aspect ratio, ignore the requirement
        if (optimalSize == null) {
            minDiff = Double.MAX_VALUE;
            for (Camera.Size size : sizes) {
                if (Math.abs(size.height - targetHeight) < minDiff) {
                    optimalSize = size;
                    minDiff = Math.abs(size.height - targetHeight);
                }
            }
        }
        return optimalSize;
    }

    @Override
    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {

        mCamera = Camera.open();
        Camera.Parameters parameters = mCamera.getParameters();//得到摄像头的参数

//        parameters.setPreviewSize(WIDTH / 2, HEIGHT);//设置预览照片的大小
        List<Camera.Size> sizeList = parameters.getSupportedPreviewSizes();//获取所有支持的camera尺寸
        for(Camera.Size size : sizeList){
            Log.e("TAG_AII", ">>>>>>>>setPreviewSize("+size.width+" ,   "+  size.height+")");

        }
//        Log.e("TAG_AII", "-----------setPreviewSize("+surfaceView.getWidth()+" ,   "+  surfaceView.getHeight()+")");
        Camera.Size optionSize = getOptimalPreviewSize(sizeList, 720, 720);//
        Log.e("TAG_AII", "setPreviewSize("+optionSize.width+" ,   "+ optionSize.height+")");
        parameters.setPreviewSize(optionSize.width,optionSize.height);
//        parameters.setPreviewSize(640 ,   480);
        parameters.setPreviewFrameRate(12);//设置每秒8帧
        parameters.setPictureFormat(ImageFormat.NV21);//设置照片的格式
//        parameters.setPictureFormat(PixelFormat.JPEG);//设置照片的格式
        parameters.setJpegQuality(80);//设置照片的质量
//        parameters.setPictureSize(WIDTH / 2, HEIGHT);//设置照片的大小，默认是和   屏幕一样大


        try {
            mCamera.setPreviewCallback(new CameraPreviewCallback());
            mCamera.setPreviewTexture(surface);
//            mCamera.setPreviewDisplay(surfaceView.getHolder());//通过SurfaceView显示取景画面

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                mCamera.setAutoFocusMoveCallback(new Camera.AutoFocusMoveCallback() {
                    @Override
                    public void onAutoFocusMoving(boolean start, Camera camera) {
//                        if(start){
//                            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
//                                mCamera.setAutoFocusMoveCallback(null);
//                            }
//                        }
                        Log.i(TAG, "对焦" + start);
                    }
                });
            }
            mCamera.startPreview();
        } catch (IOException ioe) {
            // Something bad happened
            ioe.printStackTrace();
        }

    }
    public static Bitmap byteToBitmap(byte[] imgByte) {
        InputStream input = null;
        Bitmap bitmap = null;
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inSampleSize = 1;
        input = new ByteArrayInputStream(imgByte);
        SoftReference softRef = new SoftReference(BitmapFactory.decodeStream(
                input, null, options));
        bitmap = (Bitmap) softRef.get();
        if (imgByte != null) {
            imgByte = null;
        }

        try {
            if (input != null) {
                input.close();
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return bitmap;
    }

    class CameraPreviewCallback implements Camera.PreviewCallback {
        @Override
        public void onPreviewFrame(final byte[] data, final Camera camera) {
            new Handler(Looper.getMainLooper()).post(new Runnable() {
                @Override
                public void run() {

                    try {
                        Canvas canvas = surfaceView.getHolder().lockCanvas();
                        if (canvas != null) {
                            Camera.Size size = camera.getParameters().getPreviewSize();
                            try {
                                YuvImage image = new YuvImage(data, ImageFormat.NV21, size.width, size.height, null);
//                        YuvImage image = new YuvImage(data, ImageFormat.NV21, (WIDTH / 2), HEIGHT, null);
                                if (image != null) {
                                    ByteArrayOutputStream stream = new ByteArrayOutputStream();
                                    Rect oriRect = new Rect(0, 0, size.width, size.height);
//                            Rect oriRect = new Rect(0, 0, (WIDTH / 2), HEIGHT);
                                    image.compressToJpeg(oriRect, 80, stream);
//                            Bitmap bmp = BitmapFactory.decodeByteArray(stream.toByteArray(), 0, stream.size());
                                    Bitmap bmp = byteToBitmap(stream.toByteArray());

                                    if(bmp != null){
//                                        bmp = scaleBitmap(bmp, (WIDTH / 2), HEIGHT);
//                                if (size.height != HEIGHT) {
                                    canvas.drawBitmap(bmp, oriRect, new RectF(0, 0, (WIDTH / 2), HEIGHT), paint);
//                                } else {
//                                        canvas.drawBitmap(bmp, 0, 0, paint);
//                                }
                                        bmp.recycle();
                                    }


                                }
                            } catch (Exception e) {
                                e.printStackTrace();
                            } finally {
                                if (canvas != null) {
                                    surfaceView.getHolder().unlockCanvasAndPost(canvas);
                                }
                            }
                        }
                    } catch (Exception e){
                        e.printStackTrace();
                    }
                }
            });
        }
    }
    /**
     * 根据给定的宽和高进行拉伸
     *
     * @param origin    原图
     * @param newWidth  新图的宽
     * @param newHeight 新图的高
     * @return new Bitmap
     */
    private Bitmap scaleBitmap(Bitmap origin, int newWidth, int newHeight) {
        if (origin == null) {
            return null;
        }
        int height = origin.getHeight();
        int width = origin.getWidth();
        float scaleWidth = ((float) newWidth) / width;
        float scaleHeight = ((float) newHeight) / height;
        Matrix matrix = new Matrix();
        matrix.postScale(scaleWidth, scaleHeight);// 使用后乘
        Bitmap newBM = Bitmap.createBitmap(origin, 0, 0, width, height, matrix, false);
        if (!origin.isRecycled()) {
            origin.recycle();
        }
        return newBM;
    }



    @Override
    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
        // Ignored, Camera does all the work for us
    }

    @Override
    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
        try {
            mCamera.setPreviewCallback(null) ;
            mCamera.stopPreview();
            mCamera.release();
            isRun = false;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return true;
    }

    @Override
    public void onSurfaceTextureUpdated(SurfaceTexture surface) {
        // Invoked every time there's a new Camera preview frame
    }
//
//
//                mParameters.setZoom((int) (progress * 1.0f / (maxZoom * 100) * maxZoom));
//                mCamera.setParameters(mParameters);
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {


        if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
            Camera.Parameters mParameters = mCamera.getParameters();
            int zoom = mParameters.getZoom();
            if(zoom > 0){
                zoom--;
                mParameters.setZoom(zoom);
            }
            mCamera.setParameters(mParameters);
            return true;
        }
        else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
            Camera.Parameters mParameters = mCamera.getParameters();
            int zoom = mParameters.getZoom();
            if(zoom < mParameters.getMaxZoom()){
                zoom++;
                mParameters.setZoom(zoom);
            }
            mCamera.setParameters(mParameters);
            return true;
        }

        return super.onKeyDown(keyCode, event);
    }
}